#!/usr/bin/python

"""
    This file is part of benjap.

    Copyright Graham Jones 2011.

    Benjap is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    banjap is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with benjap (COPYING file).  
    If not, see <http://www.gnu.org/licenses/>.

    $Id$
"""
"""
fireworks application

"""
import os    

# Start pygame
from appBase import appBase
import pygame
from pygame.locals import QUIT, KEYDOWN, \
    K_ESCAPE, MOUSEBUTTONDOWN, MOUSEMOTION, K_q, K_F4
from random import random, randint, choice
from math import sin,cos,pi

class fireworkApp(appBase):

    def __init__(self,parent):
    
        print "fireworkApp.__init__()"
        appBase.__init__(self,parent)

        self.Sprites = pygame.sprite.RenderUpdates()
        self.origin=(int(self.screen_size[0]/2),
                     int(self.screen_size[1]/2))

        self.screen.fill((0,0,0))
        pygame.display.flip()

        # Make overgrown pixel map
        self.pix_list = []
        for rgb_tuple in pygame.color.THECOLORS.values():
            if sum(rgb_tuple) > 509:
                pix_surf = pygame.Surface((3, 3))
                pix_surf.fill(rgb_tuple)
                self.pix_list.append(pix_surf.convert())
        del rgb_tuple, pix_surf

        # Get 'white elephant' firework data, and re-orientate
        # it to put its origin at the centre.
        self.eData = []
        eData_tmp = []
        eFile = open("elephant.dat","r")
        eLines = eFile.readlines()
        av_x = 0
        av_y = 0
        for eLine in eLines:
            pt_x = int(eLine.split()[0])
            pt_y = int(eLine.split()[1])
            print "point is (%d,%d)." % (pt_x,pt_y)
            eData_tmp.append((pt_x,pt_y))
            av_x += pt_x
            av_y += pt_y
        av_x = av_x / len(eData_tmp)
        av_y = av_y / len(eData_tmp)

        # Move origin
        for pt in eData_tmp:
            x = pt[0] - av_x
            y = pt[1] - av_y
            self.eData.append((x,y))
        print "eData = ",self.eData
        del eData_tmp, eLines

        # Load Sounds
        self.explosion = pygame.mixer.Sound('sounds/blow.aif')


    def setOrigin(self,pos):
        self.origin = pos

    def processEvent(self,event):
        #print "starsApp.processEvent()"
        if event.type == MOUSEBUTTONDOWN:
            if event.button == 1:
                self.explosion.play()
                fwType = randint(0,10)
                self.makeFirework(event.pos,fwType)

    def processDisplay(self,delay=0):
        view_time = 3000.
        #star(self.origin[0],self.origin[1],dx,dy,view_time,image,self.Sprites)

    def makeFirework(self,pos,fireworkType=0):
        """
        Create a firework burst at the specified position.
        fireworkType determines the type of firework to create.  Options are
        1 - Simple colourful round burst.
        10 - White Elephant
        """
        if fireworkType < 10:
            self.makeRoundFirework(pos)
        
        elif fireworkType == 10:
            self.makeElephantFirework(pos)
        else:
            print "unrecognised firework type ", fireworkType


    def makeRoundFirework(self,pos):
        for i in range(300):
            speed = random() * 0.15 + 0.01
            angle = random()*2*pi
            dx = speed * cos(angle)
            dy = speed * sin(angle)
            particleImage = choice(self.pix_list)
            lifetime = 1000
            particle(pos[0],pos[1],dx,dy,
                     lifetime,
                     particleImage,self.Sprites)
        
    def makeElephantFirework(self,pos):
        """ 
        Make a white elephant firework.
        The coordinates of the points at their end of life are
        taken from self.eData, which should be a list of (x,y) points.
        The speed and direction required to get the point into its
        correct position at end of life are calculated as each point
        is generated.
        01/01/2011  GJ  ORIGINAL VERSION
        """
        particleImage = pygame.Surface((3, 3))
        particleImage.fill((255,255,255))

        elephantScale = 3.0
                
        for pt in self.eData:
            lifetime = 1000.  # miliseconds
            dx = elephantScale*pt[0]/lifetime
            dy = -1*elephantScale*pt[1]/lifetime
            particle(pos[0],pos[1],dx,dy,
                     lifetime,
                     particleImage,self.Sprites)
        


class particle(pygame.sprite.Sprite):
    """
    A class to describe each particle forming the firework burst.
    Note there is no friction in this version - each particle moves
    with its initial velocity until it reaches its lifetime, when
    it disappears.
    """
    def __init__(self, x, y, dx,dy, lifetime, image,*groups):
        pygame.sprite.Sprite.__init__(self, *groups)
        self.x = x
        self.y = y
        self.dx = dx
        self.dy = dy
        self.lifetime = lifetime
        self.image = image
        self.rect = self.image.get_rect(center=(int(x), int(y)))
        self.total_time = 0

    def update(self, act_delay):
        if self.total_time < self.lifetime:
            self.x = self.x + act_delay * self.dx
            self.y = self.y + act_delay * self.dy
            self.rect = self.image.get_rect(center=(int(self.x), int(self.y)))
            self.total_time += act_delay
        else:
            self.kill()



if __name__ == "__main__": 
    ml = fireworkApp(None)
    ml.mainLoop()
